/*******************************************************************************
 * Copyright (c) 2008 Sylvain Sicard.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Sylvain Sicard - initial API and implementation
 ******************************************************************************/
package fr.jade.fraclite.control.content;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.Interface;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.ContentController;
import org.objectweb.fractal.api.control.IllegalContentException;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.api.factory.InstantiationException;

import fr.jade.fraclite.ChainedNoSuchInterfaceException;
import fr.jade.fraclite.InitializationContext;
import fr.jade.fraclite.api.Controller;
import fr.jade.fraclite.api.control.SuperControllerNotifier;

/**
 * Provides a basic implementation of the {@link ContentController} interface.
 */

public class BasicContentController implements Controller, ContentController {

  protected ContentController innerImpl = null;

  public Component weaveableC;

  /**
   * The internal interfaces of the component to which this controller object
   * belongs.
   */

  public Map<String, Interface> fcInternalInterfaces;

  /**
   * The sub components of the component to which this controller object
   * belongs.
   */

  public List<Component> fcSubComponents;

  /**
   * Initializes the fields of this mixin and then calls the overriden method.
   *
   * @param ic information about the component to which this controller object
   *      belongs.
   * @throws InstantiationException if the initialization fails.
   */

  public void initFcController (final InitializationContext ic) throws InstantiationException {
    innerImpl = (ContentController)ic.content;
    fcInternalInterfaces = ic.internalInterfaces;
    fcSubComponents = new ArrayList<Component>();
    try {
      weaveableC = (Component) ((Component)ic.getInterface("component")).getFcInterface("component");
    } catch (NoSuchInterfaceException e) {
      throw new InstantiationException(e.toString());
    }
  }

  public Object[] getFcInternalInterfaces () {
    if(innerImpl == null){
      // returns the names of all the public interfaces in fcInternalInterfaces
      // interfaces whose name begins with '/' are private
      int size = 0;
      String[] names = new String[fcInternalInterfaces.size()];
      names = (String[])fcInternalInterfaces.keySet().toArray(names);
      for (int i = 0; i < names.length; ++i) {
        if (names[i].charAt(0) != '/') {
          ++size;
        }
      }
      int index = 0;
      Object[] itfs = new Object[size];
      for (int i = 0; i < names.length; ++i) {
        if (names[i].charAt(0) != '/') {
          itfs[index++] = fcInternalInterfaces.get(names[i]);
        }
      }
      return itfs;
    }else{
      return innerImpl.getFcInternalInterfaces();
    }
  }

  public Object getFcInternalInterface (final String interfaceName) throws NoSuchInterfaceException {
    if(innerImpl == null){
      Object itf;
      if (fcInternalInterfaces == null) {
        itf = null;
      } else {
        itf = fcInternalInterfaces.get(interfaceName);
      }
      if (itf == null) {
        throw new ChainedNoSuchInterfaceException(null, weaveableC, interfaceName);
      }
      return itf;
    }else{
      return innerImpl.getFcInternalInterface(interfaceName);
    }
  }

  public Component[] getFcSubComponents () {
    if(innerImpl == null){
      return (Component[])fcSubComponents.toArray(new Component[fcSubComponents.size()]);
    }else{
      return innerImpl.getFcSubComponents();
    }
  }

  public void addFcSubComponent (final Component subComponent) throws IllegalContentException, IllegalLifeCycleException {
    if(innerImpl == null){
      fcSubComponents.add(subComponent);
    }else{
      innerImpl.addFcSubComponent(subComponent);
    }
    // Notify sub component
    try {
      SuperControllerNotifier scn = (SuperControllerNotifier)subComponent.getFcInterface("super-controller");
      scn.addedToFc(weaveableC);
    } catch (NoSuchInterfaceException ignored) {  }
  }

  public void removeFcSubComponent (final Component subComponent) throws IllegalContentException, IllegalLifeCycleException {
    if(innerImpl == null){
      fcSubComponents.remove(subComponent);
    }else{
      innerImpl.removeFcSubComponent(subComponent);
    }
    // Notify sub component
    try {
      SuperControllerNotifier scn = (SuperControllerNotifier)subComponent.getFcInterface("super-controller");
      scn.removedFromFc(weaveableC);
    } catch (NoSuchInterfaceException ignored) {  }
  }
  
}
